home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianVisSticks.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
33KB
|
1,066 lines
/*
ScianVisSticks.c
Tzong-Yow Hwu
Modified from ScianVisBalls.c
Sticks visualization object in SciAn
*/
/*
Needs to do:
1. the A-corbon chain dealing way.
2. joint.
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianArrays.h"
#include "ScianWindows.h"
#include "ScianTextBoxes.h"
#include "ScianButtons.h"
#include "ScianTitleBoxes.h"
#include "ScianObjWindows.h"
#include "ScianIcons.h"
#include "ScianColors.h"
#include "ScianControls.h"
#include "ScianLists.h"
#include "ScianSliders.h"
#include "ScianIDs.h"
#include "ScianDatasets.h"
#include "ScianPictures.h"
#include "ScianDialogs.h"
#include "ScianErrors.h"
#include "ScianComplexControls.h"
#include "ScianMethods.h"
#include "ScianStyle.h"
#include "ScianVisObjects.h"
#include "ScianVisSticks.h"
#include "ScianDraw.h"
#include "ScianTemplates.h"
#include "ScianTemplateHelper.h"
#include "ScianSymbols.h"
ObjPtr visSticks; /*Class for Sticks objects*/
/* Stick Styles */
#define BAS_LINES 0
#define BAS_GIRDERS 1
#define BAS_CYLINDERS 2
/* color shading definition */
#define BAS_FLAT 0
#define BAS_SMOOTH 1
/* max number of sides of cylinder to make */
#define BAS_MAXCYLSIDES 512
#define PICSTICKBOXWID 185
static ObjPtr AddSticksControls(stick, panelContents)
ObjPtr stick, panelContents;
/*Adds controls to a stick stick*/
{
ObjPtr var;
ObjPtr titleBox, button, radio;
ObjPtr corral, textBox, icon, defaultIcon, name;
ObjPtr stickField, mainDataset;
int left, top, bottom, right;
/*Get the stick field*/
/* The difference between GetObjectVar and GetVar ?? HWU */
stickField = GetObjectVar("AddSticksControls", stick, MAINDATASET);
if (!stickField) return ObjFalse;
while (mainDataset = GetVar(stickField, MAINDATASET))
{
stickField = mainDataset;
}
right = CWINWIDTH - (2 * CORRALBORDER + CWINCORRALWIDTH);
left = right - PICSTICKBOXWID;
top = CWINHEIGHT - MINORBORDER;
bottom = top - (TITLEBOXTOP + 2 * MINORBORDER + 2 * CHECKBOXSPACING + 3 * CHECKBOXHEIGHT);
/* title box for stick style*/
titleBox = NewTitleBox(left, right, bottom, top, "Stick Style");
PrefixList(panelContents, titleBox);
SetVar(titleBox, PARENT, panelContents);
/* add radio */
radio = NewRadioButtonGroup("Stick Style Group");
PrefixList(panelContents, radio);
SetVar(radio, PARENT, panelContents);
top -= TITLEBOXTOP + MINORBORDER;
/* Make the buttons */
button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
top - CHECKBOXHEIGHT, top, "Lines");
AddRadioButton(radio, button);
button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
top - 2 * CHECKBOXHEIGHT - CHECKBOXSPACING,
top - CHECKBOXHEIGHT - CHECKBOXSPACING, "Girders");
AddRadioButton(radio, button);
button = NewRadioButton(left + MINORBORDER, (left + right) / 2,
top - 3 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING,
top - 2 * CHECKBOXHEIGHT - 2 * CHECKBOXSPACING,
"Cylinders");
AddRadioButton(radio, button);
/* figure out the stickStyle first */
var = GetIntVar("AddSticksControls", stick, STYLE);
if (!var)
{
SetVar(stick, STYLE, NewInt(BAS_LINES));
}
AssocDirectControlWithVar(radio, stick, STYLE);
SetVar(radio, HELPSTRING, NewString("This controls the style of the sticks to be visualized."));
/*Put in the stick corral at the top left*/
left = MAJORBORDER;
top = MAJORBORDER;
corral = NewIconCorral(NULLOBJ, left, left + ONECORRALWIDTH,
CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT,
CWINHEIGHT - MAJORBORDER, 0);
SetVar(corral, SINGLECORRAL, ObjTrue);
SetVar(corral, TOPDOWN, ObjTrue);
SetVar(corral, NAME, NewString("Stick Field"));
SetVar(corral, HELPSTRING, NewString("This corral shows the dataset that is \
being used to make the stick display."));
PrefixList(panelContents, corral);
SetVar(corral, PARENT, panelContents);
SetVar(corral, REPOBJ, stick);
SetMethod(corral, DROPINCONTENTS, DropInMainDatasetCorral);
/*Create the stick source text box*/
textBox = NewTextBox(left, left + ONECORRALWIDTH,
CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP - TEXTBOXHEIGHT,
CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP,
0, "Stick Field Text", "Stick Field");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
SetTextAlign(textBox, CENTERALIGN);
/*Put in an icon that represents the field*/
name = GetVar(stickField, NAME);
defaultIcon = GetVar(stickField, DEFAULTICON);
if (defaultIcon)
{
icon = NewObject(defaultIcon, 0);
SetVar(icon, NAME, name);
}
else
{
icon = NewIcon(0, 0, ICONQUESTION, GetString(name));
}
SetVar(icon, ICONLOC, NULLOBJ);
SetVar(icon, REPOBJ, stickField);
DropIconInCorral(corral, icon);
return ObjTrue;
}
#define BAS_I_THRESHOLD 0.8
/* chord extension factor */
extern double cefs_2[];
static ObjPtr MakeSticksSurface(sticks)
ObjPtr sticks;
/*Makes the surface of a stick object*/
{
ObjPtr sticksData;
ObjPtr surface;
ObjPtr var;
ObjPtr dataForm;
ObjPtr edges; /* edges defining sticks */
ObjPtr sizeObj;
int nComponents; /* # components of data form */
long nVertices; /* number of vertices */
VertexPtr *vertices; /* all the vertices */
TwoReals *edgeElements;
long maxK; /* number of edges */
long k;
TwoReals *residueElements;
long nResidues; /* number of residues */
int stickStyle; /* style of sticks to make*/
int colorShading; /* color shading of sticks to make */
real size0, size1; /* if no sizeobj, then both ends of sticks are of size
size0 ,if is sizeobj, then one end is size0 and the other size1 */
real sizefactor, sizeoffset, sizeconstant;
Bool sameForm, capEnds;
/* Get the main dataset*/
MakeVar(sticks, MAINDATASET);
if (!(sticksData = GetVar(sticks, MAINDATASET)))
{
return ObjFalse;
}
/* Get its edges */
if (!(edges = GetDatasetKEdges(sticksData, 1)))
{
return ObjFalse;
}
/*Get the number of edges */
maxK = DIMS(edges)[0];
/* Get edge's tworeal array */
edgeElements = ELEMENTS(edges);
SetCurForm(FORMFIELD, sticksData);
/* Get number of components, it should be 2 or 3 */
nComponents = GetNComponents(FORMFIELD);
if (nComponents != 2 && nComponents != 3)
{
return ObjFalse;
}
/* Get the number of vertices from the current form field */
if ( 1 != CountTraversalDims(FORMFIELD) )
{
return ObjFalse;
}
else
{
GetTraversalDims(FORMFIELD, &nVertices);
if (!nVertices)
{
return ObjTrue;
}
}
/* Create a new surface picture */
if (!(surface = NewPicture()))
{
return ObjFalse;
}
/* Caching all the vertices */
if (!(vertices = (VertexPtr *) Alloc(nVertices * sizeof(VertexPtr))))
{
OMErr();
return ObjFalse;
}
vertices[0] = NewVertex(surface, VF_FIRSTCANON);
for (k = 1; k < nVertices; k++)
{
vertices[k] = NewVertex(surface, VF_NEXTCANON);
}
for (k = 0; k < nVertices; k++)
{
vertices[k]->position[0] = SELECTFIELDCOMPONENT(FORMFIELD, 0, &k);
vertices[k]->position[1] = SELECTFIELDCOMPONENT(FORMFIELD, 1, &k);
vertices[k]->position[2] = nComponents > 2 ?
SELECTFIELDCOMPONENT(FORMFIELD, 2, &k) : 0.0;
}
/* Get color shading, 0 for flat color and 1 for smooth color */
MakeVar(sticks, COLORSHADING);
var = GetVar(sticks, COLORSHADING);
if (var)
{
colorShading = GetInt(var);
}
else
{
colorShading = BAS_FLAT;
}
/* Get stick style from STYLE variable */
MakeVar(sticks, STYLE);
var = GetVar(sticks, STYLE);
if (var)
{
stickStyle = GetInt(var);
}
else
{
stickStyle = BAS_LINES;
}
if ((stickStyle == BAS_GIRDERS) || (stickStyle == BAS_CYLINDERS))
{
MakeVar(sticks, SIZEFACTOR);
var = GetRealVar("MakeSticksSurface", sticks, SIZEFACTOR);
if (var)
{
sizefactor = GetReal(var);
}
else
{
sizefactor = 1.0;
}
MakeVar(sticks, SIZEOFFSET);
var = GetRealVar("MakeSticksSurface", sticks, SIZEOFFSET);
if (var)
{
sizeoffset = GetReal(var);
}
else
{
sizeoffset = 0.0;
}
sizeObj = NULLOBJ;
MakeVar(sticks, SIZESWITCH);
if (GetPredicate(sticks, SIZESWITCH))
{
MakeVar(sticks, SIZEOBJ);
sizeObj = GetVar(sticks, SIZEOBJ);
}
if (sizeObj)
{
SetCurField(FIELD1, sizeObj);
SetCurForm(FIELD2, sizeObj);
sameForm = IdenticalFields(FORMFIELD, FIELD2);
}
else
{
MakeVar(sticks, SIZECONSTANT);
var = GetRealVar("MakeSticksSurface", sticks, SIZECONSTANT);
if (var)
{
sizeconstant = GetReal(var);
}
else
{
sizeconstant = 0.1;
}
size0 = sizeconstant * sizefactor + sizeoffset;
}
/* see if cap is needed by users */
capEnds=GetPredicate(sticks, CAPENDSP);
}
if ((stickStyle == BAS_LINES))
{
if (colorShading == BAS_SMOOTH)
{
VertexPtr line[2];
/* appending all the edges to the surface */
for (k = 0; k < maxK; k++)
{
line[0] = vertices[(long) edgeElements[k][0]];
line[1] = vertices[(long) edgeElements[k][1]];
AppendSPolylineToPicture(surface, 1, 0, 2, line);
}
}
else /* colorShading is BAS_FLAT */
{
VertexPtr line1[2], line2[2];
for (k = 0; k < maxK; k++)
{
line1[0] = vertices[(long) edgeElements[k][0]];
line2[0] = vertices[(long) edgeElements[k][1]];
line1[1] = InsertVertex(surface, line1[0]);
line2[1] = InsertVertex(surface, line2[0]);
line1[1]->position[0] = line2[1]->position[0] =
0.5 * (line1[0]->position[0] + line2[0]->position[0]);
line1[1]->position[1] = line2[1]->position[1] =
0.5 * (line1[0]->position[1] + line2[0]->position[1]);
line1[1]->position[2] = line2[1]->position[2] =
0.5 * (line1[0]->position[2] + line2[0]->position[2]);
AppendSPolylineToPicture(surface, 1, 0, 2, line1);
AppendSPolylineToPicture(surface, 1, 0, 2, line2);
}
}
}
else if ((stickStyle == BAS_GIRDERS))
{
VertexPtr edgeVertices[2];
float a[3]; /* axial vectors */
float r[4][3]; /* the normalized radial vectors */
float rSized0[4][3], rSized1[4][3]; /* sized radial vectors */
VertexPtr gutterEnd0[8], gutterEnd1[8];
PolysPtr polys;
int i, m;
polys = AppendPolysToPicture(surface);
for (k = 0; k < maxK; k++)
{
edgeVertices[0] = vertices[(long) edgeElements[k][0]];
edgeVertices[1] = vertices[(long) edgeElements[k][1]];
/* axial vector */
for(i = 0; i < 3; i++)
{
a[i] = edgeVertices[0]->position[i] - edgeVertices[1]->position[i];
}
NORMALIZE(a);
/* get first radial vector */
if (ABS(a[0]) >= BAS_I_THRESHOLD)
{
/* by crossing with j axis vector (0, 1, 0) */
r[0][0] = -a[2]; r[0][1] = 0.0; r[0][2] = a[0];
}
else
{
/* by crossing with i axis vector (1, 0, 0) */
r[0][0] = 0.0; r[0][1] = a[2]; r[0][2] = -a[1];
}
/* needs to normalize r[0] */
NORMALIZE(r[0]);
/* get orgothonal radial vector, counterclockwisely */
CROSS(a, r[0], r[1]);
/* do not need to normalize r[1] since r[0] and a are both unit vector and they are perpendicular to each other, r[1] must be unit vector also*/
/* consider the size factor and calculate their opposite direction*/
/* r[0] and r[2] are opposite, and r[1] and r[3] opposite*/
if (sizeObj)
{
long index0, index1;
real sizeval0, sizeval1;
index0 = (long) edgeElements[k][0];
index1 = (long) edgeElements[k][1];
if (sameForm)
{
sizeval0 = SelectFieldScalar(FIELD1, &index0);
sizeval1 = SelectFieldScalar(FIELD1, &index1);
}
else
{
sizeval0 = SampleSpatScalar(FIELD1, FIELD2, 3,
edgeVertices[0]->position, true);
sizeval1 = SampleSpatScalar(FIELD1, FIELD2, 3,
edgeVertices[1]->position, true);
}
if (sizeval0 == missingData)
{
sizeval0 = 1.0;
}
if (sizeval1 == missingData)
{
sizeval1 = 1.0;
}
size0 = sizeval0 * sizefactor + sizeoffset;
size1 = sizeval1 * sizefactor + sizeoffset;
for (m = 0; m < 3; m++)
{
r[2][m] = -r[0][m];
rSized0[0][m] = r[0][m] * size0;
rSized1[0][m] = r[0][m] * size1;
rSized0[2][m] = -rSized0[0][m];
rSized1[2][m] = -rSized1[0][m];
r[3][m] = -r[1][m];
rSized0[1][m] = r[1][m] * size0;
rSized1[1][m] = r[1][m] * size1;
rSized0[3][m] = -rSized0[1][m];
rSized1[3][m] = -rSized1[1][m];
}
}
else /* no sizeObj */
{
for (m = 0; m < 3; m++)
{
r[2][m] = -r[0][m];
rSized0[0][m] = r[0][m] * size0;
rSized0[2][m] = -rSized0[0][m];
r[3][m] = -r[1][m];
rSized0[1][m] = r[1][m] * size0;
rSized0[3][m] = -rSized0[1][m];
}
}
/* vertex position */
/* group as (0,1) (2,3) (4,5) (6,7) as of the same position */
for (i = 0; i < 4; i++)
{
gutterEnd0[2 * i] = InsertVertex(surface, edgeVertices[0]);
gutterEnd0[2 * i + 1] = InsertVertex(surface, edgeVertices[0]);
gutterEnd1[2 * i] = InsertVertex(surface, edgeVertices[1]);
gutterEnd1[2 * i + 1] = InsertVertex(surface, edgeVertices[1]);
if (sizeObj)
{
for (m = 0; m < 3; m++)
{
gutterEnd0[2 * i]->position[m] =
gutterEnd0[2 * i + 1]->position[m] =
edgeVertices[0]->position[m] + rSized0[i][m];
gutterEnd1[2 * i]->position[m] =
gutterEnd1[2 * i + 1]->position[m] =
edgeVertices[1]->position[m] + rSized1[i][m];
}
}
else /* no sizeObj */
{
for (m = 0; m < 3; m++)
{
gutterEnd0[2 * i]->position[m] =
gutterEnd0[2 * i + 1]->position[m] =
edgeVertices[0]->position[m] + rSized0[i][m];
gutterEnd1[2 * i]->position[m] =
gutterEnd1[2 * i + 1]->position[m] =
edgeVertices[1]->position[m] + rSized0[i][m];
}
}
}
/* vertex normal*/
if (sizeObj && size0 != size1)
{
/* get normal of the first surface, with vertices 7 and 0 */
float axialv[3], verticalv[3], nv[3], nextnv[3];
for (m = 0; m < 3; m++)
{
axialv[m] = gutterEnd0[0]->position[m] -
gutterEnd1[0]->position[m];
verticalv[m] = gutterEnd1[7]->position[m] -
gutterEnd1[0]->position[m];
}
CROSS(axialv, verticalv, nv);
NORMALIZE(nv);
for (m = 0; m < 3; m++)
{
gutterEnd0[7]->normal[m] =
gutterEnd0[0]->normal[m] =
gutterEnd1[7]->normal[m] =
gutterEnd1[0]->normal[m] = nv[m];
}
/* now get the normals for the other surface by crossing
its previous surface's normal with the boundary vector*/
for (i = 1; i < 4; i++)
{
for (m = 0; m < 3; m++)
{
axialv[m] = gutterEnd0[2 * i - 1]->position[m] -
gutterEnd1[2 * i - 1]->position[m];
}
CROSS(axialv, nv, nextnv);
NORMALIZE(nextnv);
for (m = 0; m < 3; m++)
{
gutterEnd0[2 * i - 1]->normal[m] =
gutterEnd0[2 * i]->normal[m] =
gutterEnd1[2 * i - 1]->normal[m] =
gutterEnd1[2 * i]->normal[m] = nv[m] = nextnv[m];
}
}
}
else /* no sizeObj, or size0 == size 1 */
{
for (i = 1; i < 4; i++)
for (m = 0; m < 3; m++)
{
gutterEnd0[2 * i - 1]->normal[m] =
gutterEnd0[2 * i]->normal[m] =
gutterEnd1[2 * i - 1]->normal[m] =
gutterEnd1[2 * i]->normal[m] =
SQ22 * (r[i - 1][m] + r[i][m]);
}
for (m = 0; m < 3; m++)
{
gutterEnd0[7]->normal[m] =
gutterEnd0[0]->normal[m] =
gutterEnd1[7]->normal[m] =
gutterEnd1[0]->normal[m] = SQ22 * (r[3][m] + r[0][m]);
}
}
/* constructing the surface with the vertices */
if (colorShading == BAS_SMOOTH)
{
VertexPtr v[4];
for (i = 1; i < 4; i++)
{
v[0] = gutterEnd0[2 * i - 1];
v[1] = gutterEnd0[2 * i];
v[2] = gutterEnd1[2 * i];
v[3] = gutterEnd1[2 * i - 1];
AppendSPolyToPolys(polys, 4, v);
}
v[0] = gutterEnd0[7];
v[1] = gutterEnd0[0];
v[2] = gutterEnd1[0];
v[3] = gutterEnd1[7];
AppendSPolyToPolys(polys, 4, v);
}
else /* colorShading is BAS_FLAT */
{
VertexPtr gutterMid0[8], gutterMid1[8];
VertexPtr v[4];
/* vertex position */
/* group as (0,1) (2,3) (4,5) (6,7) as of the same position */
for (i = 0; i < 4; i++)
{
gutterMid0[2 * i] = InsertVertex(surface, edgeVertices[0]);
gutterMid0[2 * i + 1] = InsertVertex(surface, edgeVertices[0]);
gutterMid1[2 * i] = InsertVertex(surface, edgeVertices[1]);
gutterMid1[2 * i + 1] = InsertVertex(surface, edgeVertices[1]);
for (m = 0; m < 3; m++)
{
gutterMid0[2 * i]->position[m] =
gutterMid0[2 * i + 1]->position[m] =
gutterMid1[2 * i]->position[m] =
gutterMid1[2 * i + 1]->position[m] =
0.5 * (gutterEnd0[2 * i]->position[m] +
gutterEnd1[2 * i]->position[m]);
}
}
/* vertex normal*/
for (i = 0; i < 8; i++)
for (m = 0; m < 3; m++)
{
gutterMid0[i]->normal[m] =
gutterMid1[i]->normal[m] =
gutterEnd0[i]->normal[m];
}
for (i = 1; i < 4; i++)
{
v[0] = gutterEnd0[2 * i - 1];
v[1] = gutterEnd0[2 * i];
v[2] = gutterMid0[2 * i];
v[3] = gutterMid0[2 * i - 1];
AppendSPolyToPolys(polys, 4, v);
v[0] = gutterEnd1[2 * i - 1];
v[1] = gutterEnd1[2 * i];
v[2] = gutterMid1[2 * i];
v[3] = gutterMid1[2 * i - 1];
AppendSPolyToPolys(polys, 4, v);
}
v[0] = gutterEnd0[7];
v[1] = gutterEnd0[0];
v[2] = gutterMid0[0];
v[3] = gutterMid0[7];
AppendSPolyToPolys(polys, 4, v);
v[0] = gutterEnd1[7];
v[1] = gutterEnd1[0];
v[2] = gutterMid1[0];
v[3] = gutterMid1[7];
AppendSPolyToPolys(polys, 4, v);
} /* else */
/* end caps */
if (capEnds)
{
VertexPtr cap0[4], cap1[4];
for (i = 0; i < 4; i++)
{
cap0[i] = InsertVertex(surface, edgeVertices[0]);
cap1[i] = InsertVertex(surface, edgeVertices[1]);
for (m = 0; m < 3; m++)
{
cap0[i]->position[m]=gutterEnd0[2 * i]->position[m];
cap1[i]->position[m]=gutterEnd1[2 * i]->position[m];
cap0[i]->normal[m] = a[m];
cap1[i]->normal[m] = - a[m];
}
}
AppendSPolyToPolys(polys, 4, cap0);
AppendSPolyToPolys(polys, 4, cap1);
}
} /* for loop */
}
else if ((stickStyle == BAS_CYLINDERS))
{
VertexPtr edgeVertices[2];
VertexPtr cylEnd0[BAS_MAXCYLSIDES], cylEnd1[BAS_MAXCYLSIDES];
float a[3]; /* axial vectors */
float r[BAS_MAXCYLSIDES][3]; /* the normalized radial vectors */
float rSized0[BAS_MAXCYLSIDES][3],
rSized1[BAS_MAXCYLSIDES][3]; /* if size are diff. */
PolysPtr polys;
int nSubdivisions;
int curNSides = 4;
int delta;
int i, m;
/* Get number of subdivisions the users want */
MakeVar(sticks, FRUSTUMSUBDIV);
var = GetVar(sticks, FRUSTUMSUBDIV);
if (var)
{
nSubdivisions = GetInt(var);
}
else
{
nSubdivisions = 2; /* Octal sides */
}
while (nSubdivisions--) curNSides *= 2;
polys = AppendPolysToPicture(surface);
for (k = 0; k < maxK; k++)
{
edgeVertices[0] = vertices[(long) edgeElements[k][0]];
edgeVertices[1] = vertices[(long) edgeElements[k][1]];
for (i = 0; i < curNSides; i++)
{
cylEnd0[i] = InsertVertex(surface, edgeVertices[0]);
cylEnd1[i] = InsertVertex(surface, edgeVertices[1]);
}
/* axial vector */
for (i = 0; i < 3; i++)
{
a[i] = edgeVertices[0]->position[i] - edgeVertices[1]->position[i];
}
/* a is the normal vector of the plane at e1 */
NORMALIZE(a);
/* get first radial vector */
if (ABS(a[0]) >= BAS_I_THRESHOLD)
{
/* by crossing with j axis vector (0, 1, 0) */
r[0][0] = -a[2]; r[0][1] = 0.0; r[0][2] = a[0];
}
else
{
/* by crossing with i axis vector (1, 0, 0) */
r[0][0] = 0.0; r[0][1] = a[2]; r[0][2] = -a[1];
}
/* needs to normalize r[0] */
NORMALIZE(r[0]);
delta = curNSides / 4;
/* get 3 other main radial vectors */
CROSS(a, r[0], r[delta]);
/* consider the size factor and calculate their opposite direction*/
/* r[0] and r[2] are opposite, and r[1] and r[3] opposite*/
if (sizeObj)
{
long index0, index1;
real sizeval0, sizeval1;
index0 = (long) edgeElements[k][0];
index1 = (long) edgeElements[k][1];
if (sameForm)
{
sizeval0 = SelectFieldScalar(FIELD1, &index0);
sizeval1 = SelectFieldScalar(FIELD1, &index1);
}
else
{
sizeval0 = SampleSpatScalar(FIELD1, FIELD2, 3,
edgeVertices[0]->position, true);
sizeval1 = SampleSpatScalar(FIELD1, FIELD2, 3,
edgeVertices[1]->position, true);
}
if (sizeval0 == missingData)
{
sizeval0 = 1.0;
}
if (sizeval1 == missingData)
{
sizeval1 = 1.0;
}
size0 = sizeval0 * sizefactor + sizeoffset;
size1 = sizeval1 * sizefactor + sizeoffset;
for (m = 0; m < 3; m++)
{
r[2 * delta][m] = -r[0][m];
rSized0[0][m] = r[0][m] * size0;
rSized1[0][m] = r[0][m] * size1;
rSized0[2 * delta][m] = -rSized0[0][m];
rSized1[2 * delta][m] = -rSized1[0][m];
r[3 * delta][m] = -r[delta][m];
rSized0[delta][m] = r[delta][m] * size0;
rSized1[delta][m] = r[delta][m] * size1;
rSized0[3 * delta][m] = -rSized0[delta][m];
rSized1[3 * delta][m] = -rSized1[delta][m];
}
}
else /* no sizeObj */
{
for (m = 0; m < 3; m++)
{
r[2*delta][m] = -r[0][m];
rSized0[0][m] = r[0][m] * size0;
rSized0[2 * delta][m] = -rSized0[0][m];
r[3 * delta][m] = -r[delta][m];
rSized0[delta][m] = r[delta][m] * size0;
rSized0[3 * delta][m] = -rSized0[delta][m];
}
}
/* get the remaining radial vectors */
i = 0;
for ( ;delta > 1; delta /= 2 )
{
register double cef_2;
int beg;
cef_2 = cefs_2[i];
i++;
for (beg = 0; beg < curNSides; beg += delta)
{
register int mid, end; /* mid and end points */
end = (beg + delta) & (curNSides - 1); /* circular */
mid = beg + delta / 2;
for(m = 0; m < 3; m++)
{
r[mid][m] = cef_2 * (r[beg][m] + r[end][m]);
rSized0[mid][m] = r[mid][m] * size0;
if (sizeObj)
{
rSized1[mid][m] = r[mid][m] * size1;
}
}
}
}
delta = curNSides / 4;
for (i = 0; i < curNSides; i++)
{
for (m = 0; m < 3; m++)
{
/* vertex position */
cylEnd0[i]->position[m] =
edgeVertices[0]->position[m] + rSized0[i][m];
cylEnd1[i]->position[m] = (sizeObj ?
edgeVertices[1]->position[m] + rSized1[i][m] :
edgeVertices[1]->position[m] + rSized0[i][m]);
}
/* vetex normal */
if (sizeObj && size0 != size1)
{
int j;
real boundaryVector[3], nv[3];
/* circular clipping */
j = ( i + delta ) & (curNSides -1);
for (m = 0; m < 3; m++)
{
boundaryVector[m] = cylEnd0[i]->position[m] -
cylEnd1[i]->position[m];
}
CROSS(r[j], boundaryVector, nv);
NORMALIZE(nv);
for (m = 0; m < 3; m++)
{
cylEnd0[i]->normal[m] = cylEnd1[i]->normal[m] = nv[m];
}
}
else
{
for (m = 0; m < 3; m++)
{
cylEnd0[i]->normal[m] = cylEnd1[i]->normal[m] = r[i][m];
}
}
}
if (colorShading == BAS_SMOOTH)
{
VertexPtr v[4];
/* for cylinder body */
for (i = 0; i < curNSides - 1; i++)
{
v[0] = cylEnd0[i];
v[1] = cylEnd0[i + 1];
v[2] = cylEnd1[i + 1];
v[3] = cylEnd1[i];
AppendSPolyToPolys(polys, 4, v);
}
v[0] = cylEnd0[curNSides - 1];
v[1] = cylEnd0[0];
v[2] = cylEnd1[0];
v[3] = cylEnd1[curNSides - 1];
AppendSPolyToPolys(polys, 4, v);
}
else /* colorShading is BAS_FLAT */
{
VertexPtr cylMid0[BAS_MAXCYLSIDES], cylMid1[BAS_MAXCYLSIDES];
VertexPtr v[4];
for (i = 0; i < curNSides; i++)
{
cylMid0[i] = InsertVertex(surface, edgeVertices[0]);
cylMid1[i] = InsertVertex(surface, edgeVertices[1]);
}
for (i = 0; i < curNSides; i++)
for (m = 0; m < 3; m++)
{
/* vertex position */
cylMid0[i]->position[m] = cylMid1[i]->position[m] =
0.5 * (cylEnd0[i]->position[m] + cylEnd1[i]->position[m]);
/* vertex normal */
cylMid0[i]->normal[m] = cylMid1[i]->normal[m]
= cylEnd0[i]->normal[m];
}
/* constructing the surface with the vertices */
for (i = 0; i < curNSides - 1; i++)
{
v[0] = cylEnd0[i];
v[1] = cylEnd0[i + 1];
v[2] = cylMid0[i + 1];
v[3] = cylMid0[i];
AppendSPolyToPolys(polys, 4, v);
v[0] = cylEnd1[i];
v[1] = cylEnd1[i + 1];
v[2] = cylMid1[i + 1];
v[3] = cylMid1[i];
AppendSPolyToPolys(polys, 4, v);
}
v[0] = cylEnd0[curNSides - 1];
v[1] = cylEnd0[0];
v[2] = cylMid0[0];
v[3] = cylMid0[curNSides - 1];
AppendSPolyToPolys(polys, 4, v);
v[0] = cylEnd1[curNSides - 1];
v[1] = cylEnd1[0];
v[2] = cylMid1[0];
v[3] = cylMid1[curNSides - 1];
AppendSPolyToPolys(polys, 4, v);
}
/* for end caps */
if (capEnds)
{
VertexPtr cap0[BAS_MAXCYLSIDES], cap1[BAS_MAXCYLSIDES];
for (i = 0; i < curNSides; i++)
{
cap0[i] = InsertVertex(surface, edgeVertices[0]);
cap1[i] = InsertVertex(surface, edgeVertices[1]);
for (m = 0; m < 3; m++)
{
cap0[i]->position[m] = cylEnd0[i]->position[m];
cap1[i]->position[m] = cylEnd1[i]->position[m];
cap0[i]->normal[m] = a[m];
cap1[i]->normal[m] = - a[m];
}
}
AppendSPolyToPolys(polys, curNSides, cap0);
AppendSPolyToPolys(polys, curNSides, cap1);
}
} /* for loop */
}
else
{
/* no surface style */
}
/* set the pictures's MAINDATASET for facilitating ColorPictureByObject */
SetVar(surface, MAINDATASET, sticksData);
SetVar(sticks, SURFACE, surface);
SetVar(surface, REPOBJ, sticks);
Free(vertices);
return ObjTrue;
}
static ObjPtr SticksInit(sticks)
ObjPtr sticks;
/*Initializes a stick object*/
{
ObjPtr colorObj;
/* here we make maindataset and set up colorObj for sticks */
MakeVar(sticks, MAINDATASET);
SetVar(sticks, COLOROBJ, colorObj = GetVar(sticks, MAINDATASET));
if (colorObj)
{
ObjPtr mainDataset, sizeObj;
/* set the stick vis object as having color attribute */
SetVar(sticks, COLORS, ObjTrue);
/* see if there's a sizeobj associated with its main dataset */
while (mainDataset = GetVar(colorObj, MAINDATASET))
{
colorObj = mainDataset;
}
sizeObj = GetVar(colorObj, SIZEOBJ);
if (sizeObj)
{
SetVar(sticks, SIZEOBJ, sizeObj);
SetVar(sticks, SIZESWITCH, NewInt(1));
}
}
return ObjTrue;
}
static ObjPtr SetSticksMainDataset(visObj, dataSet)
ObjPtr visObj, dataSet;
/*Sets the main data set of visObj to dataSet*/
{
SetVar(visObj, MAINDATASET, dataSet);
return ObjTrue;
}
/* Initializes sticks visualization object */
void InitSticks()
{
ObjPtr icon;
/*Class for sticks */
visSticks = NewObject(visSized, 0);
AddToReferenceList(visSticks);
SetVar(visSticks, NAME, NewString("Sticks"));
SetVar(visSticks, STYLE, NewInt(BAS_LINES));
SetVar(visSticks, SIZECONSTANT, NewReal(0.1));
SetVar(visSticks, SIZEFACTOR, NewReal(1.0));
SetVar(visSticks, SIZEOFFSET, NewReal(0.0));
SetMethod(visSticks, INITIALIZE, SticksInit);
/* notice a new icon is created for this stick visobj */
SetVar(visSticks, DEFAULTICON, icon = NewObject(visIcon, 0));
SetVar(icon, WHICHICON, NewInt(ICONSTICKS));
SetVar(icon, NAME, NewString("Sticks"));
SetVar(icon, HELPSTRING,
NewString("This icon represents a stick visualization object. \
This object is used to display a skeleton of molecular structure."));
DeclareIndirectDependency(visSticks, SURFACE, MAINDATASET, DATA);
DeclareDependency(visSticks, SURFACE, STYLE);
/* surface depends on colorshading */
SetVar(visSticks, COLORSHADING, ObjFalse); /* set colorshading flat */
DeclareDependency(visSticks, SURFACE, COLORSHADING);
SetMethod(visSticks, SURFACE, MakeSticksSurface);
SetMethod(visSticks, SETMAINDATASET, SetSticksMainDataset);
SetMethod(visSticks, ADDCONTROLS, AddSticksControls);
icon = NewIcon(0, 0, ICONSTICKS, "Sticks");
SetVar(icon, HELPSTRING,
NewString("Click on this icon to see a panel of controls for the stick object."));
SetVar(visSticks, CONTROLICON, icon);
DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_UNSTRUCTURED, 1, 3, 1, visSticks);
DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_UNSTRUCTURED, 1, 2, 1, visSticks);
}
void KillSticks()
/*Kills sticks visualization*/
{
DeleteThing(visSticks);
}